from __future__ import absolute_import
import logging
from os.path import join, exists
from forest.api import Command, get_tool
import ConfigParser
logger = logging.getLogger('forest.commands.Authconfig')

# many possible values - so just copy as-is, and make the cfgfile
# conform w the expected format

#http://stackoverflow.com/questions/2885190/using-pythons-configparser-to-read-a-file-without-section-name

def skip(prefix, txt):
    if txt.startswith(prefix):
        return txt[len(prefix):]
    return txt

class Authconfig(Command):
    ''' Copies yaml lines which go there to authconfig file, then
    calls the authconfig command with all the specified parameters.

        For example::

            authconfig:
              USESHADOW: yes
              PASSWDALGORITHM: sha512
              USECRACKLIB: no

        Refer to /etc/sysconfig/authconfig man page (http://linux.die.net/man/8/authconfig)
    '''
    __register__ = 'commands.setup.Authconfig'

    def run(self, config):

        self.args = config.get('authconfig', False)

        if not self.args:
            return

        install_tree = config.get_install_root()
        auth_path = join(install_tree, 'etc', 'sysconfig', 'authconfig')

        auth_cfg = ConfigParser.ConfigParser()
        if not exists(auth_path):
            open(auth_path, 'w').write('')

        # TODO: use stringio here
        auth_cfg.readfp(get_tool('files.FakeSect')(open(auth_path)))

        for key, val in self.args.iteritems():
            if key == '$command':
                continue
            if isinstance(val, bool):
                val = 'yes' if val else 'no'
            auth_cfg.set('asection', key, val)

        auth_args = []
        auth_lst = []
        #exhaustive I believe
        cmd_only_val = ['ldapserver', 'ldapbasedn', 'krb5kdc', 'krb5adminserver',
        'krb5realm', 'winbindjoin', 'winbindtemplateshell',
        'winbindtemplateprimarygroup', 'winbindtemplatehomedir',
        'winbindseparator', 'smbidmapgid', 'smbidmapuid', 'smbworkgroup',
        'smbservers', 'smbrealm', 'smbsecurity', 'smartcardaction',
        'smartcardmodule', 'ldaploadcacert', 'nisserver', 'nisdomain']
        #possibly non-exhaustive
        cmd_only_bool = ['usepreferdns', 'usewinbindoffline',
        'usewinbindusedefaultdomain', 'usewinbindauth', 'userfc2307bis',
        'useldaptls']
        #possibly non-exhaustive
        # not sure if usedb and use passqdqc are file-only
        translate = {
            'fprintd': 'fingerprint',
            'kerberos': 'krb5',
            'forcesmartcard': 'requiresmartcard'
        }
        for key, val in auth_cfg.items('asection'):
            prefix = 'enable' if val == 'yes' else 'disable'

            # because that's the only one that has a value yet is present
            # in both
            if key.lower() == 'passwordalgorithm':
                auth_args.append('--passalgo='.format(val))
                auth_lst.append('{0}={1}\n'.format(key.upper(), val))
            elif key.lower() in cmd_only_val:
                auth_args.append('-ldaptls-{0}={1}'.format(key, val))
            elif key.lower() in cmd_only_bool:
                #so the format is consistent in our .yaml
                switch_name = skip('use', key.lower())
                auth_args.append('--{0}{1}'.format(prefix, switch_name))
            else:
                cut_key = skip('use', key.lower())
                switch_name = translate.get(cut_key, cut_key)
                auth_args.append('--{0}{1}'.format(prefix, switch_name))
                auth_lst.append('{0}={1}\n'.format(key.upper(), val))

        get_tool('files.write')(auth_path, ''.join(auth_lst))
        with get_tool('system.chroot')(install_tree):
            get_tool('system.execute')(['authconfig']+auth_args)
